package com.jihox.abookpro.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

import com.jihox.abookpro.MyApplication;
import com.jihox.abookpro.R;

/**
 * 本地图片加载器,采用的是异步解析本地图片，单例模式利用getInstance()获取NativeImageLoader实例
 * 调用loadNativeImage()方法加载本地图片，此类可作为一个加载本地图片的工具类
 */
public class NativeImageLoader {
	private JihoxLruCache<String, Bitmap> mMemoryCache;
	private static NativeImageLoader mInstance = new NativeImageLoader();
	DynamicBlockingQueue<Runnable> bqueue = new DynamicBlockingQueue<Runnable>(30); 
	public static final String jihoxUrl = "/jihox/pbandroid/.thumbnails";
	private ThreadPoolExecutor mImageThreadPool = new ThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue); 

	private int getCacheSize(Context context) {  
        // According to the phone memory, set a proper cache size for LRU cache  
        // dynamically.  
        final ActivityManager am = (ActivityManager)context  
                .getSystemService(Context.ACTIVITY_SERVICE);  
        final int memClass = am.getMemoryClass();  
  
        int cacheSize;  
        if (memClass <= 24) {  
            cacheSize = (memClass << 20) / 24;  
        } else if (memClass <= 36) {  
            cacheSize = (memClass << 20) / 18;  
        } else if (memClass <= 48) {  
            cacheSize = (memClass << 20) / 12;  
        } else {  
            cacheSize = (memClass << 20) >> 3;  
        }  
        
//        cacheSize = memClass/4;
   
        System.out.println("cacheSize == "+cacheSize);  
        return cacheSize;  
    }  
	
	private NativeImageLoader(){

		mMemoryCache = new JihoxLruCache<String, Bitmap>(getCacheSize(MyApplication.getInstance())) {

			//获取每张图片的大小
			@Override
			protected int sizeOf(String key, Bitmap bitmap) {
				return bitmap.getRowBytes() * bitmap.getHeight();  
			}
			
//			@Override  
//            protected void entryRemoved(boolean evicted, String key, Bitmap oldValue,  
//                    Bitmap newValue) {  
//                if (evicted && oldValue != null && !oldValue.isRecycled()) {  
//                    oldValue.recycle();  
//                    oldValue = null;  
//                }  
//            }  
		};
	}

	public void clearCache(){
		//		detailCache.evictAll();
		mMemoryCache.evictAll();
	}
	public void clearCacheButTheSelectedPhotoList(ArrayList<AndroidImageFile> selectedPhotoList){
		ArrayList<String> newList = new ArrayList<String>();
		for(AndroidImageFile aif : selectedPhotoList){
			newList.add(aif.getPath());
		}
		mMemoryCache.evictAllButTheList(newList);
	}
	public void removeItemFromCache(String key){
		mMemoryCache.remove(key);
	}
	/**
	 * 通过此方法来获取NativeImageLoader的实例
	 * @return
	 */
	public static NativeImageLoader getInstance(){
		return mInstance;
	}
	//	public void clearDetailCache(){
	//		detailCache.evictAll();
	//	}

	/**
	 * 加载本地图片，对图片不进行裁剪
	 * @param path
	 * @param mCallBack
	 * @return
	 */
	public Bitmap loadNativeImage(final AndroidImageFile file,Context context, final NativeImageCallBack mCallBack){
		return this.loadNativeImage(file, null,context, mCallBack);
	}
	/**
	 * 此方法来加载本地图片，这里的mPoint是用来封装ImageView的宽和高，我们会根据ImageView控件的大小来裁剪Bitmap
	 * 如果你不想裁剪图片，调用loadNativeImage(final String path, final NativeImageCallBack mCallBack)来加载
	 * @param path
	 * @param mPoint
	 * @param mCallBack
	 * @return
	 */
	public Bitmap loadNativeImage(final AndroidImageFile aif, final Point mPoint,final Context context, final NativeImageCallBack mCallBack){
		//先获取内存中的Bitmap
		Bitmap bitmap = getBitmapFromMemCache(aif.getPath());
		final Handler mHander = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				mCallBack.onImageLoader((Bitmap)msg.obj, aif);
			}
		};

		//若该Bitmap不在内存缓存中，则启用线程去加载本地的图片，并将Bitmap加入到mMemoryCache中
		if(bitmap == null || bitmap.isRecycled()){
			//			final Uri mImageUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
			//			final ContentResolver mContentResolver = context.getContentResolver();
			mImageThreadPool.execute(new Runnable() {

				@Override
				public void run() {
					//先获取图片的缩略图
					String dirPath = Environment.getExternalStorageDirectory()+ jihoxUrl;
					String path = dirPath+"/"+aif.getPath().replace("/", "-");
					Bitmap mBitmap = null;
					File file=new File(path);
					if(!file.exists()){
						mBitmap = decodeThumbBitmapForFile(aif.getPath(), mPoint == null ? 400: mPoint.x, mPoint == null ? 400: mPoint.y);
						String sdStatus = Environment.getExternalStorageState(); 
						if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用 
							Toast.makeText(context, context.getResources().getString(R.string.T_NoSD_NoThumbnail), Toast.LENGTH_SHORT).show(); 
						} else{
							FileOutputStream fos = null; 
							File dir = new File(dirPath);
							if(!dir.exists()&&!dir.isDirectory()){
								dir.mkdirs();// 创建文件夹 
							}
							try { 
								//								int extIndex = path.lastIndexOf(".");
								//								int nameIndex = path.lastIndexOf("/"); 
								//这有个问题：图片缩略图cache应该定期清除，本来createtempfile可以解决的，在jvm结束时清除，
								//但它创建文件时会自动添加后缀名，需要建立一个表来维护，此处先放置不做了。
								//								File tempFile = File.createTempFile(path.substring(nameIndex+1, extIndex), path.substring(extIndex), dir );  
								fos = new FileOutputStream(path); 
								if (mBitmap!=null && fos!=null){
									mBitmap.compress( Bitmap.CompressFormat.JPEG, 90, fos);    
								}
								
							} catch (FileNotFoundException e) { 
								e.printStackTrace(); 
							}finally { 
								try { 
									if(fos!=null){
										fos.flush();
										fos.close();   
									}
								} catch (IOException e) { 
									e.printStackTrace(); 
								} 
							}
						}
					}else{
						mBitmap = decodeThumbBitmapForFile(path, mPoint == null ? 400: mPoint.x, mPoint == null ? 400: mPoint.y);
						//						mBitmap = BitmapFactory.decodeFile(path);
					}

					//					if(aif.getId()>-1){
					//						Cursor mCursor = mContentResolver.query(mImageUri,null,MediaStore.Images.Thumbnails.IMAGE_ID+"=? ",new String[]{aif.getId()+""},null);
					//						if(mCursor.moveToNext()){
					//							Log.i("Original",path);
					//							path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA));
					//							Log.i("Thumnails Thumnails:", path);
					//						}
					//						mCursor.close();
					//					}

					Message msg = mHander.obtainMessage();
					msg.obj = mBitmap;
					mHander.sendMessage(msg);
					if (mBitmap!=null && !mBitmap.isRecycled()){
						//将图片加入到内存缓存
						addBitmapToMemoryCache(aif.getPath(), mBitmap);
					}
				}
			});
		}
		//		mHander.post(new Runnable() {
		//
		//			@Override
		//			public void run() {
		//				//先获取图片的缩略图
		//				Bitmap mBitmap = decodeThumbBitmapForFile(path, mPoint == null ? 400: mPoint.x, mPoint == null ? 400: mPoint.y);
		//				Message msg = mHander.obtainMessage();
		//				msg.obj = mBitmap;
		//				mHander.sendMessage(msg);
		//
		//				//将图片加入到内存缓存
		//				addBitmapToMemoryCache(path, mBitmap);
		//			}
		//		});
		return bitmap;
	}
	/**
	 * loadDetail bit map,  destroy when size exceed 3
	 */
	public Bitmap loadNativeImageForDetail(final AndroidImageFile aif, final Point mPoint, final NativeImageCallBack mCallBack){
		//先获取内存中的Bitmap
		Bitmap bitmap = getBitmapFromMemCache(aif.getPath()+"-detail");

		final Handler mHander = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				mCallBack.onImageLoader((Bitmap)msg.obj, aif);
			}
		};

		if(bitmap == null){
			//			final Uri mImageUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
			//			final ContentResolver mContentResolver = context.getContentResolver();
			mImageThreadPool.execute(new Runnable() {

				@Override
				public void run() {
					//先获取图片的缩略图
					Bitmap mBitmap = null;
					mBitmap = decodeThumbBitmapForFile(aif.getPath(), mPoint == null ? 1000: mPoint.x, mPoint == null ? 1000: mPoint.y);
					Message msg = mHander.obtainMessage();
					msg.obj = mBitmap;
					mHander.sendMessage(msg);
					addBitmapToMemoryCache(aif.getPath()+"-detail", mBitmap);
				}
			});
		}
		return bitmap;
	}
	// loadNativeImageSync同步获取图片
	public Bitmap loadNativeImageSync(final String path, final Point mPoint,boolean addToCache){
		//先获取内存中的Bitmap
		Bitmap bitmap = null;
		bitmap = getBitmapFromMemCache(path);
		if (bitmap!=null && bitmap.isRecycled()){
			mMemoryCache.remove(path);
			bitmap =null;
		}
		if(bitmap==null){
			bitmap = decodeThumbBitmapForFile(path, mPoint == null ? 400: mPoint.x, mPoint == null ? 400: mPoint.y);
			if (addToCache){
				addBitmapToMemoryCache(path, bitmap);
			}
		}
		//将图片加入到内存缓存
		return bitmap;
	}
	
	// loadNativeImageSync同步获取图片
	public Bitmap loadCoverImageForShare(final String path, final Point mPoint,boolean addToCache){
		//先获取内存中的Bitmap
		Bitmap bitmap = null;
		bitmap = getBitmapFromMemCache(path+"-share");
		if(bitmap==null){
			bitmap = decodeThumbBitmapForFile(path, mPoint == null ? 600: mPoint.x, mPoint == null ? 600: mPoint.y);
			if (addToCache){
				addBitmapToMemoryCache(path+"-share", bitmap);
			}
		}
		//将图片加入到内存缓存
		return bitmap;
	}
		
	public Bitmap loadNativeImageSyncAndOriginal(final String path,boolean forceFormSDCard){//加载原始尺寸的bitmap，不裁剪
		//先获取内存中的Bitmap
		Bitmap bitmap = null;
		if(!forceFormSDCard){
			bitmap = getBitmapFromMemCache(path);
		}
		if(bitmap==null || bitmap.isRecycled()){

			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inPreferredConfig = Bitmap.Config.RGB_565;
			//设置为false,解析Bitmap对象加入到内存中
			options.inJustDecodeBounds = false;
			options.inPurgeable = true;
			options.inInputShareable = true;
			//			int degree = PictureUtil.readPictureDegree(path);
			//			if (degree != 0) {// 旋转照片角度
			//				bitmap = PictureUtil.rotateBitmap(BitmapFactory.decodeFile(path, options), degree);
			//			}
			//			else{
			try{
				bitmap = BitmapFactory.decodeFile(path, options);
			}
			catch(Exception e){
				System.out.println("exception:"+e.getMessage());
			}
			//			}
			addBitmapToMemoryCache(path, bitmap);
		}
		//将图片加入到内存缓存
		return bitmap;
	}
	/**
	 * 往内存缓存中添加Bitmap
	 * @param key
	 * @param bitmap
	 */
	public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
		if (bitmap != null) {
			//			int size1 = bitmap.getRowBytes();
			//			int sss = size1 * bitmap.getHeight();
			//			int size  = bitmap.getByteCount()/1024;
			mMemoryCache.put(key, bitmap);
		}
	}
	/**
	 * @param key
	 * @param bitmap
	 */
	//	private void addBitmapToDetailCache(String key, Bitmap bitmap) { //这里可能有bug，就是图片超级大，一个cache存不下
	//		if (getBitmapFromDetailCache(key) == null && bitmap != null) {
	//			//			detailCache.evictAll();
	//			//			if(detailCache.size()>3){
	//			//				detailCache.remove(detailCacheList.get(0));	// it may exist consistent problem
	//			//				detailCacheList.remove(0);
	//			//			}
	//			detailCache.put(key, bitmap);
	//			//			detailCacheList.add(key);
	//		}
	//	}
	/**
	 * 根据key来获取内存中的图片
	 * @param key
	 * @return
	 */
	public Bitmap getBitmapFromMemCache(String key) {
		if(mMemoryCache.get(key)!=null&&mMemoryCache.get(key).isRecycled()){
			return null;
		}
		return mMemoryCache.get(key);
	}
	/**
	 * 根据key来获取内存中的详细图片
	 * @param key
	 * @return
	 */
	//	private Bitmap getBitmapFromDetailCache(String key) {
	//		return detailCache.get(key);
	//	}
	/**
	 * 根据View(主要是ImageView)的宽和高来获取图片的缩略图
	 * @param path
	 * @param viewWidth
	 * @param viewHeight
	 * @return
	 */
	private Bitmap decodeThumbBitmapForFile(String path, int viewWidth, int viewHeight){


		BitmapFactory.Options options = new BitmapFactory.Options();
		//设置为true,表示解析Bitmap对象，该对象不占内存
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		//设置缩放比例
		options.inSampleSize = computeScale(options, viewWidth, viewHeight);
		options.inPreferredConfig = Bitmap.Config.RGB_565;
		//设置为false,解析Bitmap对象加入到内存中
		options.inJustDecodeBounds = false;
		options.inPurgeable = true;
		options.inInputShareable = true;
		int degree = PictureUtil.readPictureDegree(path);
		if (degree != 0) {// 旋转照片角度
			return PictureUtil.rotateBitmap(BitmapFactory.decodeFile(path, options), degree);
		}
		else{
			return BitmapFactory.decodeFile(path, options);
		}
	}


	/**
	 * 根据View(主要是ImageView)的宽和高来计算Bitmap缩放比例。默认不缩放
	 * @param options
	 * @param width
	 * @param height
	 */
	private int computeScale(BitmapFactory.Options options, int viewWidth, int viewHeight){
		int inSampleSize = 1;
		if(viewWidth == 0 || viewWidth == 0){
			return inSampleSize;
		}
		int bitmapWidth = options.outWidth;
		int bitmapHeight = options.outHeight;

		//假如Bitmap的宽度或高度大于我们设定图片的View的宽高，则计算缩放比例
		if(bitmapWidth > viewWidth || bitmapHeight > viewWidth){
			int widthScale = Math.round((float) bitmapWidth / (float) viewWidth);
			int heightScale = Math.round((float) bitmapHeight / (float) viewWidth);

			//为了保证图片不缩放变形，我们取宽高比例最小的那个
			if (widthScale > heightScale ){
				inSampleSize = heightScale;
				if (widthScale-heightScale>2){
					inSampleSize = heightScale + (widthScale-heightScale)/2;
				}
			}else{
				inSampleSize = widthScale;
				if (heightScale-widthScale>2){
					inSampleSize = widthScale + (heightScale-widthScale)/2;
				}
			}
			
		}
		return inSampleSize;
	}


	/**
	 * 加载本地图片的回调接口
	 * 
	 */
	public interface NativeImageCallBack{
		/**
		 * 当子线程加载完了本地的图片，将Bitmap和图片路径回调在此方法中
		 * @param bitmap
		 * @param path
		 */
		public void onImageLoader(Bitmap bitmap, AndroidImageFile aif);
	}
}
